package com.thoughtworks.bytecode2class.tools;

import com.thoughtworks.bytecode2class.ClassVisitor;
import com.thoughtworks.bytecode2class.MethodAndFieldRef;
import com.thoughtworks.bytecode2class.attribute.Attribute;
import com.thoughtworks.bytecode2class.attribute.Code;
import com.thoughtworks.bytecode2class.attribute.CodeAttribute;
import com.thoughtworks.bytecode2class.instruction.Instruction;

import java.util.HashMap;
import java.util.Map;

public class StaticsInvocationVisitor implements ClassVisitor {

    public final Map<String, Integer> map;

    public StaticsInvocationVisitor() {
        this.map = new HashMap<String, Integer>();
    }

    public void beginConstants() {
    }

    public void beginFields() {
    }

    public void acceptMedhodAndFieldRef(MethodAndFieldRef method) {

    }

    public void beginMethods() {
    }

    public void visitMethod(MethodAndFieldRef method) {
        CodeAttribute codeAttribute = method.getCodeAttribute();
        if (codeAttribute == null) {
            return;
        }

        Code code = codeAttribute.getCode();
        for (Instruction instruction : code) {
            String opMemoni = instruction.getMemoni();
            if (map.get(opMemoni) == null) {
                map.put(opMemoni, 0);
            }

            map.put(opMemoni, map.get(opMemoni) + 1);
        }
    }

    public void beginAttributes() {
    }

    public void visitAttribute(Attribute attribute) {
    }

    public int invocationSets() {
        int sum = 0;
        for (int s : map.values()) {
            sum += s;
        }
        return sum;
    }

    public String report() {
        StringBuilder builder = new StringBuilder();
        builder.append(map.size() + " kinds of invocation set been invoked.\n");
        builder.append(invocationSets() + " invocations been invoked.\n");
        builder.append(map.toString());
        return builder.toString();
    }
}
